package sweet.mvc.api

import sweet.helper.{ Logger }
import scala.collection.{ mutable }

/** A Request Route object used route and search controller and action handler in Sweet application. */
case class ReqRoute(
  val contextName: String, val dispatcherName: String, 
  val controllerName: String, val handlerName: String, val query: String){
    
  def contextPath = contextName
  def dispatcherPath = contextName+dispatcherName
  def controllerPath = dispatcherPath+controllerName
  def handlerPath = controllerPath+handlerName
}

/** A container to hold all action handlers */
trait Controller extends Logger {
  /** Action Handler type is just a anonymous func with req and resp as parameters and return views. */
  type Handler = Function2[Req, Resp, View]
  
  /** abstract control to add action handler. */
  def handlers = _handlers.readOnly
  val _handlers = new mutable.HashMap[String, Handler]
      
  /** Add empty parameter handler. */
  def handle(url: String)(handler: =>View){ 
    _handlers(url) = (req: Req, resp: Resp) => handler 
  }
  
  /** Add req parameter only handler. */
  def handleReq(url: String)(handler: (Req)=>View){ 
    _handlers(url) = (req: Req, resp: Resp) => handler(req) 
  }
  
  /** Add req and resp parameters handler. */
  def handleResp(url: String)(handler: (Resp, Req)=>View){ 
    _handlers(url) = (req: Req, resp: Resp) => handler(resp, req) 
  }
  
  /** Subclass may override this to control how handler is lookup. */
  def findHandler(reqRoute: ReqRoute): Option[Handler] = _handlers.get(reqRoute.handlerName)
}

/** A implementation of controller that check if no handler is found, then
 * return a View handler that points to handlerName, else just return
 * the handler that's found.
 */
class HandlerNameViewController extends Controller {   
  override def findHandler(reqRoute: ReqRoute): Option[Handler] = {
    _handlers.get(reqRoute.handlerName) match {
      case Some(handler) => Some(handler)
      case None => Some((req: Req, resp: Resp) => View(reqRoute.handlerName))
    }
  }  
}
